package com.cybertooth.dbconvenience.query.core;

import com.cybertooth.dbconvenience.query.conditions.ColumnCondition;
import com.cybertooth.dbconvenience.query.conditions.ConditionGroup;
import com.cybertooth.dbconvenience.query.conditions.GroupedLogicalOperators;
import com.cybertooth.dbconvenience.query.conditions.SingleLogicalOperator;
import com.cybertooth.dbconvenience.query.enums.LogicalOperator;
import com.cybertooth.dbconvenience.query.functions.SqlTransformerFunction;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import java.util.Deque;

/**
 * <p></p>
 *
 * @author dnelson
 */
public class OnClause implements SqlTransformer, GroupedLogicalOperators<OnClause>, SingleLogicalOperator<OnClause> {

	// -----------------------------------------------------------------------Fields

	protected Deque<SqlTransformer> conditions;

	// -----------------------------------------------------------------Constructors

	public static OnClause on(ConditionGroup conditionGroup) {
		return new OnClause(conditionGroup);
	}

	public static OnClause on(ColumnCondition columnCondition) {
		return new OnClause(columnCondition);
	}

	private OnClause(ConditionGroup conditionGroup) {
		this.conditions = Lists.newLinkedList();
		this.conditions.push(conditionGroup);
	}

	private OnClause(ColumnCondition columnCondition) {
		this.conditions = Lists.newLinkedList();
		this.conditions.push(columnCondition);
	}

	// --------------------------------------------------------------Private Methods

	private void addOperatorAndCondition(LogicalOperator logicalOperator, SqlTransformer condition) {
		this.conditions.push(logicalOperator);
		this.conditions.push(condition);
	}

	// ---------------------------------------------------------------Public Methods

	/**
	 * {@inheritDoc}
	 */
	@Override
	public OnClause and(ColumnCondition columnCondition) {
		this.addOperatorAndCondition(LogicalOperator.AND, columnCondition);
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public OnClause or(ColumnCondition columnCondition) {
		this.addOperatorAndCondition(LogicalOperator.OR, columnCondition);
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public OnClause not(ColumnCondition columnCondition) {
		this.addOperatorAndCondition(LogicalOperator.NOT, columnCondition);
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public OnClause and(ConditionGroup conditionGroup) {
		this.addOperatorAndCondition(LogicalOperator.AND, conditionGroup);
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public OnClause or(ConditionGroup conditionGroup) {
		this.addOperatorAndCondition(LogicalOperator.AND, conditionGroup);
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public OnClause not(ConditionGroup conditionGroup) {
		this.addOperatorAndCondition(LogicalOperator.AND, conditionGroup);
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toSql() {
		return new StringBuilder()
				.append(" ON ")	// TODO: shouldn't need a bracket here...unit test the eff outta this
				.append(Iterables.transform(this.conditions, new SqlTransformerFunction()))
				.append(" ")
				.toString();

	}
}
